﻿namespace AB.ServiceDirectory.Dao
{
    using System.Data.SqlClient;
    using System.Linq;
    using System.Transactions;
    using Commons.DataFilters;
    using Entities;

    /// <summary>
    /// DirectorateDao Class
    /// </summary>
    public class DirectorateDao
    {
        /// <summary>
        /// Data Context
        /// </summary>
        private readonly ServicesDirectoryDataContext _context = DB.Context;

        /// <summary>
        /// Gets the list.
        /// </summary>
        /// <param name="filter">The filter.</param>
        /// <param name="sortType">Type of the sort.</param>
        /// <param name="startRowIndex">Start index of the row.</param>
        /// <param name="max">The max.</param>
        /// <returns></returns>
        public IQueryable<Directorate> GetList(DirectorateFilter filter, string sortType, int startRowIndex, int max)
        {
            IQueryable<Directorate> query = from p in _context.Directorates
                                            select p;

            // 1. Filter by condition
            if (filter != null)
            {
                query = GetListQuery(query, filter);
            }

            // 2. Sorting
            query = GetListSort(query, sortType);

            // 3. Limit the rows
            query = query.Skip(startRowIndex).Take(max);
            return query;
        }

        /// <summary>
        /// Checks the name of the directorate.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public bool CheckDirectorateName(string name)
        {
            Directorate directorate = _context.Directorates.FirstOrDefault(d => d.DirectorateName.Equals(name));
            return directorate != null;
        }

        /// <summary>
        /// Adds the directorate.
        /// </summary>
        /// <param name="newDirectorate">The new directorate.</param>
        /// <returns></returns>
        public bool AddDirectorate(Directorate newDirectorate)
        {
            try
            {
                using (var transaction = new TransactionScope())
                {
                    _context.Directorates.InsertOnSubmit(newDirectorate);
                    _context.SubmitChanges();
                    transaction.Complete();
                    return true;
                }
            }
            catch (SqlException exception)
            {
                Log.GetLog(this).Error(exception);
                return false;
            }
        }

        /// <summary>
        /// Edits the directorate.
        /// </summary>
        /// <param name="newDirectorate">The new directorate.</param>
        /// <returns></returns>
        public bool EditDirectorate(Directorate newDirectorate)
        {
            Directorate oldDirectory =
                _context.Directorates.FirstOrDefault(d => d.DirectorateId == newDirectorate.DirectorateId);
            if (oldDirectory != null)
            {
                oldDirectory.DirectorateName = newDirectorate.DirectorateName;
                oldDirectory.FullDescription = newDirectorate.FullDescription;
                oldDirectory.ShortDescription = newDirectorate.ShortDescription;
                oldDirectory.CountryId = newDirectorate.CountryId;
                oldDirectory.County = newDirectorate.County;
                oldDirectory.Email = newDirectorate.Email;
                oldDirectory.Fax = newDirectorate.Fax;
                oldDirectory.PhoneNumber = newDirectorate.PhoneNumber;
                oldDirectory.CompanyNumber = newDirectorate.CompanyNumber;
                oldDirectory.CityTown = newDirectorate.CityTown;
                oldDirectory.OrganizationId = newDirectorate.OrganizationId;
                oldDirectory.WebAddress = newDirectorate.WebAddress;
                oldDirectory.CharityNumber = newDirectorate.CharityNumber;

                // Ref Key
                BusinessType business =
                    _context.BusinessTypes.FirstOrDefault(b => b.BusinessId == newDirectorate.BusinessId);
                oldDirectory.BusinessType = business;

                Address address = _context.Addresses.FirstOrDefault(a => a.AddressId == newDirectorate.AddressId);
                oldDirectory.Address = address;

                Contact contact = newDirectorate.ContactId != null
                                      ? _context.Contacts.FirstOrDefault(c => c.ContactId == newDirectorate.ContactId)
                                      : null;
                oldDirectory.Contact = contact;

                _context.SubmitChanges();
                return true;
            }
            return false;
        }

        /// <summary>
        /// Gets the directorate by id.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public Directorate GetDirectorateById(int id)
        {
            Directorate directorate = _context.Directorates.FirstOrDefault(d => d.DirectorateId == id);
            return directorate;
        }

        /// <summary>
        /// Gets the list query.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <param name="filter">The filter.</param>
        /// <returns>Filtered list</returns>
        private static IQueryable<Directorate> GetListQuery(IQueryable<Directorate> query, DirectorateFilter filter)
        {
            if (!filter.IncludeInactive)
            {
                query = query.Where(p => p.IsActive);
            }
            if (filter.OrganizationId != 0)
            {
                query = query.Where(p => filter.OrganizationId == p.OrganizationId);
            }
            if (filter.BeginningLetters != null)
            {
                query = query.Where(p => filter.BeginningLetters.Contains(p.DirectorateName[0].ToString()));
            }

            return query;
        }

        /// <summary>
        /// Gets the list sort.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <param name="sortType">Type of the sort.</param>
        /// <returns>Sorted list</returns>
        private static IQueryable<Directorate> GetListSort(IQueryable<Directorate> query, string sortType)
        {
            bool sortDescending = false;
            if (!string.IsNullOrEmpty(sortType))
            {
                string[] values = sortType.Split(' ');
                sortType = values[0];

                if (values.Length > 1)
                {
                    sortDescending = true;
                }

                switch (sortType)
                {
                    case "DirectorateName":
                        query = sortDescending
                                    ? query.OrderByDescending(g => g.DirectorateName)
                                    : query.OrderBy(g => g.DirectorateName);
                        break;

                    case "ContactName":
                        query = sortDescending
                                    ? query.OrderByDescending(g => g.Contact.FirstName).ThenBy(g => g.Contact.Surname)
                                    : query.OrderBy(g => g.Contact.FirstName).ThenBy(g => g.Contact.Surname);
                        break;

                    case "ShortDescription":
                        query = sortDescending
                                    ? query.OrderByDescending(g => g.ShortDescription)
                                    : query.OrderBy(g => g.ShortDescription);
                        break;

                    case "IsActive":
                        query = sortDescending
                                    ? query.OrderByDescending(g => g.IsActive)
                                    : query.OrderBy(g => g.IsActive);
                        break;
                    default:
                        query = sortDescending
                                    ? query.OrderByDescending(g => g.DirectorateId)
                                    : query.OrderBy(g => g.DirectorateId);
                        break;
                }
            }

            return query;
        }

        /// <summary>
        /// Gets the list count.
        /// </summary>
        /// <param name="filter">The filter.</param>
        /// <returns>Number of rows</returns>
        public int GetListCount(DirectorateFilter filter)
        {
            IQueryable<Directorate> data = from directorate in _context.Directorates
                                           select directorate;
            if (filter != null)
            {
                data = GetListQuery(data, filter);
            }
            return data.Count();
        }

        /// <summary>
        /// Sets the directorate status.
        /// </summary>
        /// <param name="directorateId">The directorate id.</param>
        /// <param name="status">if set to <c>true</c> [status].</param>
        public void SetDirectorateStatus(int directorateId, bool status)
        {
            Directorate directorate = _context.Directorates.FirstOrDefault(d => d.DirectorateId == directorateId);
            if (directorate != null)
            {
                directorate.IsActive = status;
                _context.SubmitChanges();
            }
        }
    }
}